package com.atguigu.yygh.hosp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.hosp.dao.DepartmentRepository;
import com.atguigu.yygh.hosp.service.DepartmentService;
import com.atguigu.yygh.model.hosp.Department;
import com.atguigu.yygh.vo.hosp.DepartmentVo;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author 孔德成
 * @slogan 致敬大师，致敬未来的你
 * @date 2021/9/3 7:26 下午
 * @desc
 */
@Service
public class DepartmentServiceImpl implements DepartmentService {
    private final DepartmentRepository departmentRepository;

    public DepartmentServiceImpl(DepartmentRepository departmentRepository) {
        this.departmentRepository = departmentRepository;
    }

    @Override
    public void save(Map<String, Object> map) {
        // 1. 将 map 转为 json 字符串，再将 json 字符串转为 bean 对象
        Department department = JSONObject.parseObject(JSONObject.toJSONString(map), Department.class);
        // 2. 根据医院编号和科室编号查询科室信息
        Department departmentQuery = departmentRepository.findDepartmentByHoscodeAndDepcode(department.getHoscode(), department.getDepcode());
        // 3. 如果科室不存在，说明是第一次上传
        if (ObjectUtil.isNull(departmentQuery)) {
            // 初始化科室的其他信息：状态，逻辑删除字段，创建时间，更新时间，
            // 0 未删除；1 删除
            department.setIsDeleted(0);
            department.setCreateTime(new Date());
            department.setUpdateTime(department.getCreateTime());
        } else {
            // 科室存在，使用已存在信息填充其他空字段，执行更新操作
            department.setId(departmentQuery.getId());
            department.setIsDeleted(departmentQuery.getIsDeleted());
            department.setCreateTime(department.getCreateTime());
            department.setUpdateTime(new Date());
        }
        // 4. 保存（插入MongoDB）
        departmentRepository.save(department);
    }

    @Override
    public Page<Department> selectPage(Map<String, Object> map) {
        // 参数校验
        Object page = map.get("page");
        if (ObjectUtil.isNull(page)) {
            page = 1;
        }
        Object limit = map.get("limit");
        if (ObjectUtil.isNull(limit)) {
            limit = 10;
        }

        // 根据创建时间降序排序
        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
        // mongodb 0 为第一页
        PageRequest pageOf = PageRequest.of(Convert.toInt(page) - 1, Convert.toInt(limit), sort);

        // 创建查询条件, 根据医院编号查询所有科室
        Department department = new Department();
        department.setHoscode(Convert.toStr(map.get("hoscode")));
        Example<Department> exampleOf = Example.of(department);

        return departmentRepository.findAll(exampleOf, pageOf);
    }

    @Override
    public void remove(String hoscode, String depcode) {
        // 1. 先查询再删除
        Department department = departmentRepository.findDepartmentByHoscodeAndDepcode(hoscode, depcode);
        if (ObjectUtil.isNotNull(department)) {
            departmentRepository.deleteById(department.getId());
        }

    }

    @Override
    public List<DepartmentVo> findDeptTree(String hoscode) {
        // 1. 根据医院编号，查询医院所有科室列表
        Department departmentQuery = new Department();
        departmentQuery.setHoscode(hoscode);
        Example<Department> example = Example.of(departmentQuery);
        List<Department> departmentList = departmentRepository.findAll(example);

        // 2. 根据大科室编号  bigcode 分组，获取每个大科室里面下级子科室（ bigcode 相同的科室分到一个组）
        // 大科室只是逻辑分组，数据库没有对应的科室记录
        Map<String, List<Department>> deparmentMap =
                departmentList.stream().collect(Collectors.groupingBy(Department::getBigcode));


        // 3. 创建list集合，用于最终数据封装
        List<DepartmentVo> result = new ArrayList<>();
        deparmentMap.forEach((bigcode, departments) -> {
            // 3.1 封装大科室
            DepartmentVo bigD = new DepartmentVo();
            // 3.2 设置科室编号
            bigD.setDepcode(bigcode);
            // 3.3 设置科室名字
            bigD.setDepname(departments.get(0).getBigname());
            // 3.4 设置小科室, 将 Department 映射成 DepartmentVo
            // 只需要封装科室编号和名字即可，因为小科室没有子节点
            List<DepartmentVo> children = departments.stream()
                    .map(department -> BeanUtil.toBean(department, DepartmentVo.class))
                    .collect(Collectors.toList());
            bigD.setChildren(children);
            // 3.5 将封装好的大科室添加到结果集中
            result.add(bigD);
        });

        return result;

    }
}
